﻿using FFmpeg.AutoGen;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FFmpegWinui3.MediaFolder
{
    public abstract unsafe class MediaBase
    {
        public AVFormatContext* Format { get; protected set; }
        public AVCodecContext* CodecContext { get; protected set; }
        public AVStream* Stream { get; protected set; }
        public abstract AVMediaType Type { get; protected set; }
        public int StreamIndex;
        public string CodecName { get; protected set; }
        public int Bitrate { get; protected set; }
        public AVCodecID CodecId { get; protected set; }

        public List<MediaFrame> FrameQuene = new List<MediaFrame>();

        protected double FrameRate;
        public MediaBase(AVFormatContext* format, int streamIndex)
        {
            //创建编解码上下文
            CodecContext = ffmpeg.avcodec_alloc_context3(null);
            //设置流索引
            StreamIndex = streamIndex;
            //设置流
            Stream = format->streams[streamIndex];
            // 设置编解码器选项
            var setCodecParamsResult = ffmpeg.avcodec_parameters_to_context(CodecContext, Stream->codecpar);
            if (setCodecParamsResult < 0)
                return;
            //寻找指定的解码器
            var codec = ffmpeg.avcodec_find_decoder(Stream->codecpar->codec_id);
            if (codec == null)
                return;
            //打开解码器
            ffmpeg.avcodec_open2(CodecContext, codec, null);
            //解码器id
            CodecId = Stream->codecpar->codec_id;
            //解码器名字
            CodecName = ffmpeg.avcodec_get_name(CodecId);
            //比特率
            Bitrate = (int)Stream->codecpar->bit_rate;

        }
        public int MaxFrameCount = 20;
        int index = 0;
        public void AddFrame(AVFrame* frame, TimeSpan time)
        {

            var mediaFrame = new MediaFrame(frame, Stream->time_base);
            if (Type == AVMediaType.AVMEDIA_TYPE_AUDIO)
            {
                index++;

                Debug.WriteLine(index + " : " + mediaFrame.StartTime.ToString() + mediaFrame.Duration.ToString());
            }
            if (mediaFrame.EndTime < time)
            {
                mediaFrame.DisponseFrame();
                return;
            }
            FrameQuene.Add(mediaFrame);
        }

        public void ClearFrame()
        {
            while (FrameQuene.Count > 0)
            {
                var temp = FrameQuene[0];
                FrameQuene.Remove(temp);
                temp.DisponseFrame();
                temp = null;
            }
            CurrentFrame = null;
        }
        protected MediaFrame CurrentFrame;

        public virtual MediaFrame GetNextFrame(TimeSpan time)
        {
            if (FrameQuene.Count <= 0)
                return null;
            if (CurrentFrame != null && CurrentFrame.StartTime <= time && CurrentFrame.EndTime >= time)
                return CurrentFrame;

            while (FrameQuene.Count > 0)
            {
                var temp = FrameQuene[0];
                if (temp.EndTime < time)
                    FrameQuene.Remove(temp);
                else
                    break;
            }

            var select = FrameQuene.FirstOrDefault(item => item.StartTime <= time && item.EndTime >= time);
            return select;
        }

        protected void DisposeFrame()
        {
            if (CurrentFrame == null)
                return;
            CurrentFrame.DisponseFrame();
            CurrentFrame = null;
        }
        public abstract byte[] GetNextFrameData(TimeSpan time);
    }





}
